#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
智能题目生成服务
使用AI生成编程题目、测试用例和解答
"""

import json
import logging
from typing import Dict, List, Optional
from datetime import datetime
from .llm_service import LLMService

class ProblemGenerator:
    """智能题目生成器"""
    
    def __init__(self, llm_service: LLMService = None):
        self.llm_service = llm_service or LLMService(provider='deepseek')
        self.logger = logging.getLogger(__name__)
        
        # 题目生成角色设定
        self.generator_role = """你是一个专业的编程题目生成专家，专门为在线判题系统生成高质量的编程题目。

你的特点：
1. 能够生成不同难度级别的题目
2. 提供清晰的题目描述和输入输出格式
3. 生成全面的测试用例
4. 提供详细的解题思路和参考代码
5. 确保题目的原创性和教育价值
6. 考虑不同编程语言的特点

请严格按照指定的JSON格式返回结果。"""
    
    def generate_problem(self, topic: str, difficulty: str = 'medium', 
                        language: str = 'python') -> Dict:
        """生成编程题目"""
        try:
            prompt = f"""{self.generator_role}

请为以下要求生成一个编程题目：

主题：{topic}
难度：{difficulty}
编程语言：{language}

请生成一个完整的编程题目，包括：
1. 题目标题
2. 题目描述
3. 输入输出格式
4. 示例
5. 测试用例
6. 解题思路
7. 参考代码

请严格按照以下JSON格式返回：

{{
    "title": "题目标题",
    "description": "详细的题目描述",
    "input_format": "输入格式说明",
    "output_format": "输出格式说明",
    "examples": [
        {{
            "input": "输入示例",
            "output": "输出示例",
            "explanation": "示例解释"
        }}
    ],
    "test_cases": [
        {{
            "input": "测试输入",
            "output": "期望输出"
        }}
    ],
    "solution": {{
        "approach": "解题思路",
        "code": "参考代码",
        "complexity": "时间复杂度分析"
    }},
    "tags": ["标签1", "标签2"],
    "difficulty": "{difficulty}",
    "language": "{language}",
    "type": "code"
}}

请确保生成的题目：
1. 难度适中，符合{difficulty}级别
2. 描述清晰，没有歧义
3. 测试用例全面
4. 代码可运行
5. 具有教育价值

请用中文回答："""
            
            messages = [{'role': 'user', 'content': prompt}]
            result = self.llm_service.call_llm(messages)
            
            if result['success']:
                try:
                    # 尝试解析JSON响应
                    content = result['content'].strip()
                    
                    # 如果内容被markdown代码块包围，提取JSON部分
                    if content.startswith('```json'):
                        content = content[7:]
                    if content.startswith('```'):
                        content = content[3:]
                    if content.endswith('```'):
                        content = content[:-3]
                    
                    content = content.strip()
                    
                    # 尝试解析JSON
                    problem_data = json.loads(content)
                    
                    # 验证必要字段
                    required_fields = ['title', 'description']
                    for field in required_fields:
                        if field not in problem_data:
                            raise ValueError(f"缺少必要字段: {field}")
                    
                    return {
                        'success': True,
                        'problem': problem_data,
                        'timestamp': datetime.now().isoformat(),
                        'generator_type': 'problem_generation'
                    }
                except json.JSONDecodeError as e:
                    self.logger.error(f"JSON解析失败: {str(e)}")
                    self.logger.error(f"原始内容: {result['content']}")
                    return {
                        'success': False,
                        'error': f'AI生成的题目格式不正确: {str(e)}'
                    }
                except ValueError as e:
                    self.logger.error(f"数据验证失败: {str(e)}")
                    return {
                        'success': False,
                        'error': f'题目数据不完整: {str(e)}'
                    }
            else:
                return {
                    'success': False,
                    'error': result['error']
                }
                
        except Exception as e:
            self.logger.error(f"题目生成失败: {str(e)}")
            return {
                'success': False,
                'error': str(e)
            }

    def generate_choice_problem(self, topic: str, difficulty: str = 'medium', 
                               question_type: str = 'single', option_count: int = 4) -> Dict:
        """生成选择题"""
        try:
            prompt = f"""你是一个专业的编程教育专家，专门生成高质量的选择题。

请为以下要求生成一个选择题：

主题：{topic}
难度：{difficulty}
题目类型：{'单选题' if question_type == 'single' else '多选题'}
选项数量：{option_count}

请生成一个完整的选择题，包括：
1. 题目标题
2. 题目描述
3. 选项列表
4. 正确答案
5. 解析说明

请严格按照以下JSON格式返回：

{{
    "title": "题目标题",
    "description": "详细的题目描述",
    "options": [
        "选项A",
        "选项B",
        "选项C",
        "选项D"
    ],
    "answer": "正确答案（如：A 或 A,B）",
    "explanation": "详细的解析说明",
    "difficulty": "{difficulty}",
    "type": "choice",
    "tags": ["标签1", "标签2"]
}}

请确保生成的题目：
1. 难度适中，符合{difficulty}级别
2. 描述清晰，没有歧义
3. 选项合理，有干扰性
4. 答案明确，解析详细
5. 具有教育价值

请用中文回答："""
            
            messages = [{'role': 'user', 'content': prompt}]
            result = self.llm_service.call_llm(messages)
            
            if result['success']:
                try:
                    # 尝试解析JSON响应
                    content = result['content'].strip()
                    
                    # 如果内容被markdown代码块包围，提取JSON部分
                    if content.startswith('```json'):
                        content = content[7:]
                    if content.startswith('```'):
                        content = content[3:]
                    if content.endswith('```'):
                        content = content[:-3]
                    
                    content = content.strip()
                    
                    # 尝试解析JSON
                    problem_data = json.loads(content)
                    
                    # 验证必要字段
                    required_fields = ['title', 'description', 'options', 'answer']
                    for field in required_fields:
                        if field not in problem_data:
                            raise ValueError(f"缺少必要字段: {field}")
                    
                    return {
                        'success': True,
                        'problem': problem_data,
                        'timestamp': datetime.now().isoformat(),
                        'generator_type': 'choice_problem_generation'
                    }
                except json.JSONDecodeError as e:
                    self.logger.error(f"JSON解析失败: {str(e)}")
                    self.logger.error(f"原始内容: {result['content']}")
                    return {
                        'success': False,
                        'error': f'AI生成的选择题格式不正确: {str(e)}'
                    }
                except ValueError as e:
                    self.logger.error(f"数据验证失败: {str(e)}")
                    return {
                        'success': False,
                        'error': f'选择题数据不完整: {str(e)}'
                    }
            else:
                return {
                    'success': False,
                    'error': result['error']
                }
                
        except Exception as e:
            self.logger.error(f"选择题生成失败: {str(e)}")
            return {
                'success': False,
                'error': str(e)
            }

    def generate_blank_problem(self, topic: str, difficulty: str = 'medium', 
                              blank_count: int = 3) -> Dict:
        """生成填空题"""
        try:
            prompt = f"""你是一个专业的编程教育专家，专门生成高质量的填空题。

请为以下要求生成一个填空题：

主题：{topic}
难度：{difficulty}
填空数量：{blank_count}

请生成一个完整的填空题，包括：
1. 题目标题
2. 题目描述（包含填空位置）
3. 正确答案
4. 解析说明

请严格按照以下JSON格式返回：

{{
    "title": "题目标题",
    "description": "详细的题目描述，用 ___ 表示填空位置",
    "answer": "正确答案（多个答案用逗号分隔）",
    "explanation": "详细的解析说明",
    "difficulty": "{difficulty}",
    "type": "blank",
    "tags": ["标签1", "标签2"]
}}

请确保生成的题目：
1. 难度适中，符合{difficulty}级别
2. 描述清晰，填空位置明确
3. 答案准确，解析详细
4. 具有教育价值

请用中文回答："""
            
            messages = [{'role': 'user', 'content': prompt}]
            result = self.llm_service.call_llm(messages)
            
            if result['success']:
                try:
                    # 尝试解析JSON响应
                    content = result['content'].strip()
                    
                    # 如果内容被markdown代码块包围，提取JSON部分
                    if content.startswith('```json'):
                        content = content[7:]
                    if content.startswith('```'):
                        content = content[3:]
                    if content.endswith('```'):
                        content = content[:-3]
                    
                    content = content.strip()
                    
                    # 尝试解析JSON
                    problem_data = json.loads(content)
                    
                    # 验证必要字段
                    required_fields = ['title', 'description', 'answer']
                    for field in required_fields:
                        if field not in problem_data:
                            raise ValueError(f"缺少必要字段: {field}")
                    
                    return {
                        'success': True,
                        'problem': problem_data,
                        'timestamp': datetime.now().isoformat(),
                        'generator_type': 'blank_problem_generation'
                    }
                except json.JSONDecodeError as e:
                    self.logger.error(f"JSON解析失败: {str(e)}")
                    self.logger.error(f"原始内容: {result['content']}")
                    return {
                        'success': False,
                        'error': f'AI生成的填空题格式不正确: {str(e)}'
                    }
                except ValueError as e:
                    self.logger.error(f"数据验证失败: {str(e)}")
                    return {
                        'success': False,
                        'error': f'填空题数据不完整: {str(e)}'
                    }
            else:
                return {
                    'success': False,
                    'error': result['error']
                }
                
        except Exception as e:
            self.logger.error(f"填空题生成失败: {str(e)}")
            return {
                'success': False,
                'error': str(e)
            }

    def generate_short_problem(self, topic: str, difficulty: str = 'medium', 
                              question_type: str = 'concept') -> Dict:
        """生成简答题"""
        try:
            prompt = f"""你是一个专业的编程教育专家，专门生成高质量的简答题。

请为以下要求生成一个简答题：

主题：{topic}
难度：{difficulty}
题目类型：{question_type}

请生成一个完整的简答题，包括：
1. 题目标题
2. 题目描述
3. 参考答案
4. 评分要点

请严格按照以下JSON格式返回：

{{
    "title": "题目标题",
    "description": "详细的题目描述和要求",
    "answer": "参考答案",
    "scoring_points": ["评分要点1", "评分要点2", "评分要点3"],
    "difficulty": "{difficulty}",
    "type": "short",
    "tags": ["标签1", "标签2"]
}}

请确保生成的题目：
1. 难度适中，符合{difficulty}级别
2. 描述清晰，要求明确
3. 答案完整，评分要点清晰
4. 具有教育价值

请用中文回答："""
            
            messages = [{'role': 'user', 'content': prompt}]
            result = self.llm_service.call_llm(messages)
            
            if result['success']:
                try:
                    # 尝试解析JSON响应
                    content = result['content'].strip()
                    
                    # 如果内容被markdown代码块包围，提取JSON部分
                    if content.startswith('```json'):
                        content = content[7:]
                    if content.startswith('```'):
                        content = content[3:]
                    if content.endswith('```'):
                        content = content[:-3]
                    
                    content = content.strip()
                    
                    # 尝试解析JSON
                    problem_data = json.loads(content)
                    
                    # 验证必要字段
                    required_fields = ['title', 'description', 'answer']
                    for field in required_fields:
                        if field not in problem_data:
                            raise ValueError(f"缺少必要字段: {field}")
                    
                    return {
                        'success': True,
                        'problem': problem_data,
                        'timestamp': datetime.now().isoformat(),
                        'generator_type': 'short_problem_generation'
                    }
                except json.JSONDecodeError as e:
                    self.logger.error(f"JSON解析失败: {str(e)}")
                    self.logger.error(f"原始内容: {result['content']}")
                    return {
                        'success': False,
                        'error': f'AI生成的简答题格式不正确: {str(e)}'
                    }
                except ValueError as e:
                    self.logger.error(f"数据验证失败: {str(e)}")
                    return {
                        'success': False,
                        'error': f'简答题数据不完整: {str(e)}'
                    }
            else:
                return {
                    'success': False,
                    'error': result['error']
                }
                
        except Exception as e:
            self.logger.error(f"简答题生成失败: {str(e)}")
            return {
                'success': False,
                'error': str(e)
            }
    
    def generate_test_cases(self, problem_description: str, 
                           language: str = 'python') -> Dict:
        """为现有题目生成测试用例"""
        try:
            prompt = f"""{self.generator_role}

请为以下编程题目生成全面的测试用例：

题目描述：{problem_description}
编程语言：{language}

请生成包含以下类型的测试用例：
1. 基本功能测试
2. 边界条件测试
3. 特殊情况测试
4. 性能测试（大数据量）
5. 错误输入测试

请严格按照以下JSON格式返回：

{{
    "test_cases": [
        {{
            "name": "测试用例名称",
            "input": "输入数据",
            "output": "期望输出",
            "type": "测试类型",
            "description": "测试说明"
        }}
    ],
    "categories": {{
        "basic": "基本功能测试数量",
        "edge": "边界条件测试数量",
        "special": "特殊情况测试数量",
        "performance": "性能测试数量",
        "error": "错误输入测试数量"
    }}
}}

请确保测试用例：
1. 覆盖全面
2. 输入输出格式正确
3. 包含各种边界情况
4. 有清晰的测试说明

请用中文回答："""
            
            messages = [{'role': 'user', 'content': prompt}]
            result = self.llm_service.call_llm(messages)
            
            if result['success']:
                try:
                    test_cases_data = json.loads(result['content'])
                    return {
                        'success': True,
                        'test_cases': test_cases_data,
                        'timestamp': datetime.now().isoformat(),
                        'generator_type': 'test_case_generation'
                    }
                except json.JSONDecodeError as e:
                    self.logger.error(f"JSON解析失败: {str(e)}")
                    return {
                        'success': False,
                        'error': 'AI生成的测试用例格式不正确，请重试'
                    }
            else:
                return {
                    'success': False,
                    'error': result['error']
                }
                
        except Exception as e:
            self.logger.error(f"测试用例生成失败: {str(e)}")
            return {
                'success': False,
                'error': str(e)
            }
    
    def analyze_solution(self, problem_description: str, user_code: str,
                        language: str = 'python') -> Dict:
        """分析用户解答"""
        try:
            prompt = f"""{self.generator_role}

请分析以下用户提交的代码解答：

题目描述：{problem_description}
用户代码：
```{language}
{user_code}
```

请从以下方面进行分析：
1. 代码正确性
2. 算法效率
3. 代码风格
4. 可读性
5. 改进建议

请严格按照以下JSON格式返回：

{{
    "analysis": {{
        "correctness": {{
            "score": 0-100,
            "comment": "正确性评价"
        }},
        "efficiency": {{
            "score": 0-100,
            "comment": "效率评价"
        }},
        "style": {{
            "score": 0-100,
            "comment": "代码风格评价"
        }},
        "readability": {{
            "score": 0-100,
            "comment": "可读性评价"
        }}
    }},
    "suggestions": [
        "改进建议1",
        "改进建议2"
    ],
    "overall_score": 0-100,
    "grade": "优秀/良好/及格/不及格"
}}

请确保分析：
1. 客观公正
2. 具体详细
3. 有建设性
4. 鼓励为主

请用中文回答："""
            
            messages = [{'role': 'user', 'content': prompt}]
            result = self.llm_service.call_llm(messages)
            
            if result['success']:
                try:
                    analysis_data = json.loads(result['content'])
                    return {
                        'success': True,
                        'analysis': analysis_data,
                        'timestamp': datetime.now().isoformat(),
                        'generator_type': 'solution_analysis'
                    }
                except json.JSONDecodeError as e:
                    self.logger.error(f"JSON解析失败: {str(e)}")
                    return {
                        'success': False,
                        'error': 'AI生成的分析结果格式不正确，请重试'
                    }
            else:
                return {
                    'success': False,
                    'error': result['error']
                }
                
        except Exception as e:
            self.logger.error(f"解答分析失败: {str(e)}")
            return {
                'success': False,
                'error': str(e)
            }
    
    def generate_hints(self, problem_description: str, 
                      user_progress: str = '') -> Dict:
        """生成解题提示"""
        try:
            progress_context = f"\n用户当前进度：{user_progress}" if user_progress else ""
            
            prompt = f"""{self.generator_role}

请为以下编程题目生成解题提示：

题目描述：{problem_description}{progress_context}

请生成分层次的解题提示，从简单到复杂：

请严格按照以下JSON格式返回：

{{
    "hints": [
        {{
            "level": 1,
            "hint": "第一层提示（最基础）",
            "description": "提示说明"
        }},
        {{
            "level": 2,
            "hint": "第二层提示（进阶）",
            "description": "提示说明"
        }},
        {{
            "level": 3,
            "hint": "第三层提示（详细）",
            "description": "提示说明"
        }}
    ],
    "approach": "整体解题思路",
    "key_points": [
        "关键点1",
        "关键点2"
    ]
}}

请确保提示：
1. 循序渐进
2. 启发思考
3. 不直接给答案
4. 适合不同水平

请用中文回答："""
            
            messages = [{'role': 'user', 'content': prompt}]
            result = self.llm_service.call_llm(messages)
            
            if result['success']:
                try:
                    hints_data = json.loads(result['content'])
                    return {
                        'success': True,
                        'hints': hints_data,
                        'timestamp': datetime.now().isoformat(),
                        'generator_type': 'hint_generation'
                    }
                except json.JSONDecodeError as e:
                    self.logger.error(f"JSON解析失败: {str(e)}")
                    return {
                        'success': False,
                        'error': 'AI生成的提示格式不正确，请重试'
                    }
            else:
                return {
                    'success': False,
                    'error': result['error']
                }
                
        except Exception as e:
            self.logger.error(f"提示生成失败: {str(e)}")
            return {
                'success': False,
                'error': str(e)
            }
